#define BLINKER_BLE

#include <Servo.h>
#include <Blinker.h>
#include <DHT.h>     // 包含DHT头文件

//蓝牙，串口BLE模块的 TXD连接到UNO的2号引脚，RXD连接到UNO的3号引脚
//超声波，温湿度传感器
#define Echo 9 //
#define Trag 10 //定义超声波传感器的收发引脚
#define DHTPIN 12    // 定义DHT11模块连接管脚也可以通过gpio去进行定义
#define DHTTYPE DHT11 // 使用温度湿度模块的类型为DHT11


//step2,旋转，方向不用接线
unsigned int step2 = 8;

//舵机1
int ser1 = 11;
//舵机2
int ser2 = 6;
//舵机3
int ser3 = 5;

Servo servo1; // 舵机1对象
Servo servo2; // 舵机2对象
Servo servo3; // 舵机3对象


int vm = 255;

BlinkerButton btnqj("btnqj");
BlinkerButton btnht("btnht");

BlinkerButton step1u("step1u");
BlinkerButton step1d("step1d");
BlinkerButton step2x("btnxuan");
BlinkerButton btns("btns");
BlinkerButton btnj("btnj");

BlinkerJoystick joy("joy");
BlinkerSlider slider("ran");
BlinkerNumber WATER("waterdepth"); //定义水深数据按键名
BlinkerNumber HUMI("humi"); // 定义湿度数据键名
BlinkerNumber TEMP("temp"); // 定义温度数据键名

BlinkerButton opengun("opengun");
BlinkerButton closegun("closegun");
BlinkerButton upgun("upgun");
BlinkerButton downgun("downgun");
BlinkerButton stopp("stopp");

DHT dht(DHTPIN, DHTTYPE);   // 生成DHT对象，参数是引脚和DHT的类型

float humi_read = 95, temp_read = 20; // 定义浮点型全局变量 储存传感器读取的温湿度数据
float waterdepth_read = 5;  // 定义浮点型全局变量 储存传感器读取的水深数据

void btnqj_callback()
{
  Serial.println("qj");
}

void btnht_callback()
{
  Serial.println("ht");
}

void stopp_callback()
{
  Serial.println("stop");
}
void opengun_callback()
{
  Serial.println("open3");
}
void closegun_callback()
{
  Serial.println("close3");
}
void upgun_callback(const String & state)
{
  if(state == "press")
  {
    Serial.println("up4begin");
  }
  else if(state == "pressup")
  {
    Serial.println("up4end");
  }
  
}
void downgun_callback(const String & state)
{
  if(state == "press")
  {
    Serial.println("down4begin");
  }
  else if(state == "pressup")
  {
    Serial.println("down4end");
  }
}


//定义函数
unsigned long gettime()
{
    digitalWrite(Trag, HIGH);
    delayMicroseconds(10);
    digitalWrite(Trag, LOW);
    return pulseIn(Echo, HIGH);
}

void heartbeat()
{
    HUMI.print(humi_read); // 给blinkerapp回传湿度数据
    TEMP.print(temp_read); // 给blinkerapp回传温度数据
    WATER.print(waterdepth_read); //给blinkerapp回传水深数据
} // 心跳包函数，每一分钟执行一次，向app端传送信息，故而app上面关于温度和湿度指示会1min更新一次


void maichong2(int times,int speed)//times是脉冲的数量，speed是脉冲间隔，对应着电机的速度
{
  for(int x=0; x<times; x++)
  {
    digitalWrite(step2,HIGH);
    delayMicroseconds(10);//这个函数单位为微秒
    digitalWrite(step2,LOW);
    delayMicroseconds(10);//驱动器说明书规定了脉冲信号的持续时间，在规定的时间内选择尽量小的数值
    delay(speed);//前后两个脉冲之间的间隔，毫秒
    //delayMicroseconds(1000);
  }
}

void step1u_callback()
{
  
  Serial.println("up1");
  
}
void step1d_callback()//当我按下down的按钮时，竟然是先调用btn_callback，然后再调用我这个函数，这太离谱了吧
//我现在把所有的命名全部改了一遍，发现这个问题就消失了！！！！难道是命名问题，之前组件的key是btn和btndown，改成了step1u和step1d
{
  
  Serial.println("down1");
}


void controlServo(int servoNumber, int angle) {
  // 根据舵机编号选择对应的舵机对象
  Servo *servo;
  switch(servoNumber) {
    case 1:
      servo = &servo1;
      break;
    case 2:
      servo = &servo2;
      break;
    case 3:
      servo = &servo3;
      break;
    default:
      Serial.println("Invalid servo number.");
      return;
  }

  // 将舵机转动到指定角度
  servo->write(angle);
}
void stepx_callback()
{
  Serial.println("success");
  maichong2(115,10);
  delay(2000);
  controlServo(1,40);
  delay(1000);
  controlServo(2,90);
  delay(2000);
  controlServo(2,200);
  delay(100);
  controlServo(3,130);
  delay(1000);
  controlServo(1,4);
  controlServo(3,70);

}




void btns_callback()
{
  Serial.println("up2");
  
}
void btnj_callback()
{
  Serial.println("down2");
}





void slider_callback(int32_t value)
{
  vm = value;
}

void joy_callback(uint8_t xAxis,uint8_t yAxis)
{
  int x = xAxis;
  int y = yAxis;

  String message = "move(" + String(x) + "," + String(y) + ")";
  Serial.println(message);

}


void setup() {


  // pinMode(ser1, OUTPUT);
  // pinMode(ser2, OUTPUT);
  // pinMode(ser3, OUTPUT);
  servo1.attach(ser1); // 将舵机1连接到对应引脚,0,45
  servo2.attach(ser2); // 将舵机2连接到对应引脚
  servo3.attach(ser3); // 将舵机3连接到对应引脚
  //舵机初始角度
  controlServo(1,4);//4为初始，40正好转过去,11
  controlServo(2,200);//200为初始,6,90在下面
  controlServo(3,70);//张开130，闭合70,5

  Blinker.begin();
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600); // 初始化串口

  pinMode(ser1, OUTPUT);
  pinMode(ser2, OUTPUT);
  pinMode(ser3, OUTPUT);

  pinMode(Echo, INPUT);
  pinMode(Trag, OUTPUT);

  pinMode(step2, OUTPUT);//设置io口输出
  
  joy.attach(joy_callback);
  step1u.attach(step1u_callback);
  step1d.attach(step1d_callback);
  slider.attach(slider_callback);
  step2x.attach(stepx_callback);
  btns.attach(btns_callback);
  btnj.attach(btnj_callback);
  opengun.attach(opengun_callback);
  closegun.attach(closegun_callback);
  upgun.attach(upgun_callback);
  downgun.attach(downgun_callback);
  stopp.attach(stopp_callback);
  btnqj.attach(btnqj_callback);
  btnht.attach(btnht_callback);

  Blinker.attachHeartbeat(heartbeat); // 将传感器获取的数据传给blinker app上
  dht.begin(); // 初始化DHT传感器
  delay(2000);
  
}

void loop() {
  
  Blinker.run();
  float w = gettime() / 58; //读取水深并赋值给w
  float h = dht.readHumidity();    // 读取DHT11传感器的湿度 并赋值给h
  float t = dht.readTemperature(); // 读取传感器的温度   并赋值给t
  if (isnan(h) || isnan(t) )        // 判断是否成功读取到温湿度数据
  {
      BLINKER_LOG("Failed to read from DHT sensor!"); // 读取温湿度失败！
  }
  else // 成功读取到数据
  {
      // 打印
      BLINKER_LOG("Humidity: ", h, " %");
      BLINKER_LOG("Temperature: ", t, " *C");
      BLINKER_LOG("Waterdepth: ", w, " %");

      humi_read = h; // 将读取到的湿度赋值给全局变量humi_read
      temp_read = t; // 将读取到的温度赋值给全局变量temp_read
      waterdepth_read = w; //将读取到的水深赋值给全局变量water_read
  }
  HUMI.print(humi_read); // 给blinkerapp回传湿度数据
  TEMP.print(temp_read); // 给blinkerapp回传温度数据
  WATER.print(waterdepth_read); //给blinkerapp回传水深数据

  
}


